package org.zhaolei.service.impl;

import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.junit.platform.commons.util.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.zhaolei.constant.CacheKey;
import org.zhaolei.enums.BizCodeEnum;
import org.zhaolei.exception.BizException;
import org.zhaolei.interceptor.LoginInterceptor;
import org.zhaolei.model.LoginUser;
import org.zhaolei.request.CartItemRequest;
import org.zhaolei.service.CartService;
import org.zhaolei.service.ProductService;
import org.zhaolei.vo.CartItemVO;
import org.zhaolei.vo.CartVO;
import org.zhaolei.vo.ProductVO;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
@Slf4j
public class CartServiceImpl implements CartService {

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private ProductService productService;

    @Override
    public void addToCart(CartItemRequest cartItemRequest) {
        Long productId = cartItemRequest.getProductId();
        int buyNum = cartItemRequest.getBuyNum();
        //获取购物车
        BoundHashOperations<String, Object, Object> myCart = getMyCartOps();

        Object cacheObj = myCart.get(productId);
        String result = "";

        if (cacheObj != null) {
            //result是某个商品的json字符串
            result = (String)cacheObj;
        }
        if (StringUtils.isBlank(result)) {
            //购物车里原先不存在该商品
            CartItemVO cartItemVO = new CartItemVO();
            ProductVO productVO = productService.findDetailById(productId);
            if (productVO == null) {
                throw new BizException(BizCodeEnum.CART_FAIL);
            }

            cartItemVO.setAmount(productVO.getPrice());
            cartItemVO.setBuyNum(buyNum);
            cartItemVO.setProductId(productId);
            cartItemVO.setProductImg(productVO.getCoverImg());
            cartItemVO.setProductTitle(productVO.getTitle());
            myCart.put(productId, JSON.toJSONString(cartItemVO));

        } else {
            //购物车里原先存在该商品
            CartItemVO cartItemVO = JSON.parseObject(result, CartItemVO.class);
            cartItemVO.setBuyNum(cartItemVO.getBuyNum() + buyNum);
            myCart.put(productId, JSON.toJSONString(cartItemVO));
        }

    }

    @Override
    public void clear() {
        //获取当前用户的购物车key
        String currentCartKey = getCartKey();

        //清空购物车
        redisTemplate.delete(currentCartKey);
    }

    @Override
    public CartVO getMyCart() {

        //获取全部的购物车商品，false代表不需要更新商品价格
        List<CartItemVO> cartItemVOList = buildCartItem(false);

        //封装成carTVO，cartVO里的其他值都在类里自动计算了
        CartVO cartVO = new CartVO();
        cartVO.setCartItems(cartItemVOList);

        return cartVO;
    }

    /**
     * 删除购物车商品
     * @param productId
     */
    @Override
    public void deleteItem(long productId) {
        //获取当前用户的购物车
        BoundHashOperations<String, Object, Object> myCart = getMyCartOps();

        myCart.delete(productId);
    }

    /**
     * 修改购物车商品数量
     * @param cartItemRequest
     */
    @Override
    public void changeItemNum(CartItemRequest cartItemRequest) {
        //主要学习如何从redis中拿出商品信息，然后修改后再放回去
        BoundHashOperations<String,Object,Object> mycart =  getMyCartOps();

        Object cacheObj = mycart.get(cartItemRequest.getProductId());

        if(cacheObj==null){throw new BizException(BizCodeEnum.CART_FAIL);}

        String obj = (String)cacheObj;

        CartItemVO cartItemVO =  JSON.parseObject(obj,CartItemVO.class);
        cartItemVO.setBuyNum(cartItemRequest.getBuyNum());
        mycart.put(cartItemRequest.getProductId(),JSON.toJSONString(cartItemVO));
    }

    /**
     * 确认购物车商品信息
     * @param productIdList
     * @return
     */
    @Override
    public List<CartItemVO> confirmOrderCartItems(List<Long> productIdList) {
        //获取全部购物车中的购物项，并获取最新价格
        List<CartItemVO> cartItemVOList = buildCartItem(true);

        //根据需要的商品id进行过滤，并清空对应的购物项，从购物车中删除，这段代码最后剩余的是删除的商品还是没删除的商品？？？？
        List<CartItemVO> resultList =  cartItemVOList.stream().filter(obj->{

            if(productIdList.contains(obj.getProductId())){
                this.deleteItem(obj.getProductId());
                //返回true代表该项保留在resultlist中，但是从购物车中删除
                return true;
            }
            return false;

        }).collect(Collectors.toList());

        return resultList;
    }

    /**
     * 获取最新的购物项
     * @param latestPrice 是否需要更新商品价格
     * @return
     */
    private List<CartItemVO> buildCartItem(boolean latestPrice) {

        //获取购物车
        BoundHashOperations<String, Object, Object> myCart = getMyCartOps();
        //获取购物车里的商品
        List<Object> cartItemList = myCart.values();

        List<CartItemVO> cartItemVOList = new ArrayList<>();
        //商品id列表
        List<Long> productIdList = new ArrayList<>();

        for (Object cartItem : cartItemList) {
            //组装 cartItemVOList和productIdList
            CartItemVO cartItemVO = JSON.parseObject((String) cartItem, CartItemVO.class);
            cartItemVOList.add(cartItemVO);
            productIdList.add(cartItemVO.getProductId());
        }

        if (latestPrice) {
            setProductLatestPrice(cartItemVOList, productIdList);
        }

        return cartItemVOList;
    }

    private void setProductLatestPrice(List<CartItemVO> cartItemVOList, List<Long> productIdList) {

        //从数据库里查询商品的最新信息，然后更新到cartItemVOList中
        List<ProductVO> productVOList = productService.findProductsByIdBatch(productIdList);
        //把上面的list变为map，key是productId
        Map<Long, ProductVO> map = productVOList.stream().collect(Collectors.toMap(ProductVO::getId, Function.identity()));

        cartItemVOList.stream().forEach(cartItemVO -> {
            ProductVO productVO = map.get(cartItemVO.getProductId());
            cartItemVO.setAmount(productVO.getPrice());
            cartItemVO.setProductTitle(productVO.getTitle());
            cartItemVO.setProductImg(productVO.getCoverImg());
        });
    }

    private BoundHashOperations<String, Object, Object> getMyCartOps() {
        String cartKey = getCartKey();

        return redisTemplate.boundHashOps(cartKey);
    }

    /**
     * 获取当前用户的购物车key
     * @return
     */
    private String getCartKey() {
        LoginUser loginUser = LoginInterceptor.threadLocal.get();

        return String.format(CacheKey.CART_KEY, loginUser.getId());
    }
}
